<?php
namespace Modules\Order\Services;

use Modules\Order\Entities\Order;
use Illuminate\Support\Facades\Log;
use Modules\Order\Entities\Payment;
use Illuminate\Support\Facades\Auth;
use Mockery\CountValidator\Exception;

class WechatPaymentService
{
    protected $app;

    public function __construct()
    {
        $this->app = app('wechat.payment');
    }

    /**
     * 生成支付订单
     * @param $data
     * 'body' => $request->body, // 商品描述
     * 'detail' => $request->detail,// 商品详情
     * 'attach' => $request->attach, // 附加信息 {linkId, creator}
     * 'total_fee' => $follow->price, // 标价金额
     * 统一下单的扩展参数 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
     * @param callable $order_success
     * @return array 返回wx.requestPayment的调用参数
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     */
    public function pay(Order $order, string $body=null,  array $ext=null, callable $order_success = null)
    {
        // 商品详情
        // TODO: 用 Collection 改写
        $detail = null;
        $goods = $order->goods();
        if ($goods) {
            $detail = ''; // 订单商品信息 "巧克力 x 1\n咖啡 x 2"
            foreach ($goods as $item) {
                if($detail != '') $detail .= "\n";
                $detail .= $item['name'] . "\tx" . $item['count'];
            }
        }

        // 准备支付参数
        $p = array_merge([
            'openid' => Auth::user()->wechat()->first()->openid,
            'out_trade_no' => $order->sn, // 商户订单号
            'body' => $body ?: 'EMall购物',
            'detail' => $detail,
            'total_fee' => 1,//$price,
            'trade_type' => 'JSAPI', // 小程序取值如下：JSAPI
        ], (array)$ext);

        // 统一下单s
        $result = $this->app->order->unify($p);

        // 第二次签名
        if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {

            // 写入订单号
            $payment = $order->payment()->first();
            $payment->channel = Payment::CHANNEL_WECHAT;
            $payment->method = Payment::METHOD_ONLINE;
            $payment->status = Payment::STATUS_PAYING;
            $payment->save();

            if ($order_success)
                call_user_func($order_success, $order->sn);
            
            return $this->app->jssdk->sdkConfig($result['prepay_id']);
        } else {
            throw new Exception('微信支付签名失败');
        }
    }

    /**
     * 腾讯支付系统的回调
     * https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7&index=8
     * @param callable $handle function ($message, $fail)
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function paidNotify(callable $successHander=null, callable $failHander=null)
    {
        $response = $this->app->handlePaidNotify(function($message, $fail) use($successHander, $failHander){
            // 使用通知里的 "微信支付订单号" 或者 "商户订单号" 去自己的数据库找到订单
            $sn = $message['out_trade_no'];
            $order = Order::where('sn', $sn)->first();
            $payment = $order->payment();

            if (!$payment || $payment->status === Payment::STATUS_SUCCESS) { // 如果订单不存在 或者 订单已经支付过了
                return true; // 告诉微信，我已经处理完了，订单没找到，别再通知我了
            }

            /////////////TODO: <- 建议在这里调用微信的【订单查询】接口查一下该笔订单的情况，确认是已经支付 /////////////

            if ($message['return_code'] === 'SUCCESS') { // return_code 表示通信状态，不代表支付状态
                if ($message['result_code'] === 'SUCCESS') {
                    // 用户是否支付成功
                    $payment->pay_cash = $message['cash_fee'];
                    $payment->paid_at = time(); // 更新支付时间为当前时间
                    $payment->status = Payment::STATUS_SUCCESS;

                    if($successHander) $successHander($order, $message, $fail);

                } elseif ($message['result_code'] === 'FAIL') {
                    // 用户支付失败
                    $payment->status = Payment::STATUS_FAIL;
                    if($failHander) $failHander($order, $message);
                }
            } else {
                if($failHander) $failHander($order, $message);
                return $fail('通信失败'); // 通信失败，请稍后再通知我
            }

            $payment->save(); // 保存订单

            return true; // 返回处理完成
        });

        return $response;
    }
}
